//
// Created by mini on 2021/7/29.
//

import Foundation
import UIKit


//支持宽高比 和 自动列数


//vertical layout only!
public class GridX: BaseLayout {

    public class Options: Applyable {
        //宽高比
        @GreatEQ(minValue: 0)
        public var ratio: CGFloat = 1

        @GreatEQ(minValue: 0)
        public var width: CGFloat = 0

        @GreatEQ(minValue: 0)
        public var height: CGFloat = 0

        //可选
        @GreatEQ(minValue: 0)
        public var minWidth: CGFloat = 0

        @GreatEQ(minValue: 0)
        public var maxWidth: CGFloat = 0

        @GreatEQ(minValue: 0)
        public var minHeight: CGFloat = 0


        @GreatEQ(minValue: 0)
        public var maxHeight: CGFloat = 0

        public var margins: Edge = Edge()

    }

    public var paddings: Edge = Edge() {
        didSet {
            postLayout()
        }
    }


    @GreatEQ(minValue: 0)
    public var columns: Int = 3 {
        didSet {
            postLayout()
        }
    }

    @GreatEQ(minValue: 0)
    public var spaceHor: CGFloat = 0 {
        didSet {
            postLayout()
        }
    }
    @GreatEQ(minValue: 0)
    public var spaceVer: CGFloat = 0 {
        didSet {
            postLayout()
        }
    }
    public var cellOption: Options = Options()

    private var maxGap: CGFloat = 30


    override func layoutChildren(_ calcSize: CGSize?) -> CGSize {
        let childs: [UIView] = self.subviews
        if childs.isEmpty {
            return .zero
        }
        let wAll = self.bounds.width - self.paddings.left - self.paddings.right
        if wAll <= 0 {
            return .zero
        }

        let cols = max(1, calcCols(wAll))
        let cellW = calcWidth(wAll, cols)
        let cellH = calcHeight(wAll, cellW)


        let boundsX = self.bounds.origin.x
        let boundsY = self.bounds.origin.y
        var maxX: CGFloat = 0
        var maxY: CGFloat = 0
        for i in 0..<childs.count {
            let row: Int = i / cols
            let col: Int = i % cols

            let xCell: CGFloat = boundsX + self.paddings.left + (cellW + self.spaceHor) * col
            let yCell: CGFloat = boundsY + self.paddings.top + (cellH + self.spaceVer) * row
            let rectCell = Rect.sized(cellW, cellH).from(x: xCell, y: yCell)
            let rect = rectCell.inset(cellOption.margins)
            if calcSize == nil {
                childs[i].constraintStorage.updateFrame(rect)
            }
            maxX = rectCell.maxX
            maxY = rectCell.maxY
        }
        maxX += self.paddings.right
        maxY += self.paddings.bottom
        return Size(width: maxX - boundsX, height: maxY - boundsY)
    }

    private func calcHeight(_ wAll: CGFloat, _ cellW: CGFloat) -> CGFloat {
        if cellOption.height > 0 {
            return cellOption.height
        }
        if cellOption.ratio > 0 {
            return cellW / cellOption.ratio
        }
        if cellOption.minHeight > 0 {
            if cellOption.maxHeight > 0 {
                return (cellOption.minHeight + cellOption.maxHeight) / 2
            } else {
                return cellOption.minHeight
            }
        } else {
            if cellOption.maxHeight > 0 {
                return cellOption.maxHeight
            } else {
                fatalError("不能确定高度")
            }
        }
    }

    private func calcWidth(_ wAll: CGFloat, _ cols: Int) -> CGFloat {
        if cellOption.width > 0 {
            return cellOption.width
        }
        if cellOption.height > 0 && cellOption.ratio > 0 {
            return cellOption.height * cellOption.ratio
        }
        let w = (wAll + self.spaceHor) / cols - self.spaceHor
        if w > cellOption.maxWidth && cellOption.maxWidth > 0 {
            return cellOption.maxWidth
        }
        if w < cellOption.minWidth && cellOption.minWidth > 0 {
            return cellOption.minWidth
        }
        return w
    }

    private func calcCols(_ wAll: CGFloat) -> Int {
        if columns > 0 {//指定了列数
            return columns
        }

        func colsBy(cellWidth: CGFloat) -> Int {
            Int((wAll + self.spaceHor) / (cellWidth + self.spaceHor))
        }

        if cellOption.width > 0 { //指定了宽度
            return colsBy(cellWidth: cellOption.width)
        }
        if cellOption.height > 0 && cellOption.ratio > 0 {//指定了高度
            let wCell = cellOption.height * cellOption.ratio
            return colsBy(cellWidth: wCell)
        }


        func colsFloat(cellWidth: CGFloat) -> CGFloat {
            (wAll + self.spaceHor) / (cellWidth + self.spaceHor)
        }

        var maxCols: CGFloat = 0
        var minCols: CGFloat = 0
        if cellOption.minWidth > 0 {
            if cellOption.minWidth * 2 > wAll {
                return 1
            }
            maxCols = colsFloat(cellWidth: cellOption.minWidth)
        }
        if cellOption.maxWidth > 0 {
            if cellOption.maxWidth >= wAll {
                minCols = 1
            } else {
                minCols = colsFloat(cellWidth: cellOption.maxWidth)
            }
        }
        if maxCols == 0 {
            if cellOption.minHeight > 0 && cellOption.ratio > 0 {
                maxCols = colsFloat(cellWidth: cellOption.minHeight * cellOption.ratio)
            }
        }
        if minCols == 0 {
            if cellOption.maxHeight > 0 && cellOption.ratio > 0 {
                minCols = colsFloat(cellWidth: cellOption.maxHeight * cellOption.ratio)
            }
        }
        if minCols > 0 {
            if maxCols > 0 {
                let avg = (minCols + maxCols) / 2
                return Int(avg.rounded())
            } else {
                return Int(minCols)
            }
        } else {
            if maxCols > 0 {
                return Int(maxCols)
            } else {
                fatalError("不能确定列数")
            }
        }

    }

}

